home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 October / EnigmA AMIGA RUN 31 (1998)(G.R. Edizioni)(IT)[!][issue 1998-10].iso / earkit / chat / amarquee / examples / amarqueedebugmultithread.c < prev    next >
C/C++ Source or Header  |  1998-09-22  |  10KB  |  247 lines

  1.  
  2. /* This version of AMarqueeDebug creates the QSession, then
  3.    spawns a child thread and hands control of the QSession
  4.    to the child thread via QDetachSession() and QReattachSession().
  5.    There aren't any advantages to doing it this way, except
  6.    to show how (and that ;)) QDetachSession() and QReattachSession()
  7.    work. 
  8. */
  9.   
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13.  
  14. #include <dos/dos.h>
  15. #include <dos/dostags.h>
  16. #include <clib/dos_protos.h>
  17. #include <clib/exec_protos.h>
  18.  
  19. #include <clib/AMarquee_protos.h>
  20.  
  21. #include <pragmas/AMarquee_pragmas.h>
  22.  
  23. #include "include:signal.h"
  24.  
  25. struct Library * AMarqueeBase = NULL;
  26. struct QSession * session     = NULL;
  27. BOOL waitForChildThread = TRUE;
  28.  
  29. /* Takes user input until blank line is typed */
  30. void ProcessDebugCommands(struct QSession * session)
  31. {
  32.   while(1)
  33.   {
  34.    char debugline[500] = "\0\0\0\0\0\0\0\0";
  35.    char * keyword, * data;
  36.    ULONG dataLen = 0L;
  37.    LONG res;
  38.    
  39.    printf("Enter your debug command now: "); fflush(stdout);
  40.    gets(debugline);
  41.   
  42.    keyword = &debugline[2];
  43.    if (data = strchr(keyword,'='))
  44.    {
  45.      *data = '\0';  /* terminate the keyword */
  46.      data++;
  47.      dataLen = strlen(data)+1;
  48.    }
  49.    switch((int)(debugline[0]))
  50.    {
  51.      case '\0': res=QGo(session,0L);                           break;
  52.      case 'A':  res=QSetMessageAccessOp(session, keyword, -1); break;
  53.      case 'm':  res=QMessageOp(session, keyword, data, dataLen); break;
  54.      case 'M':  res=QSysMessageOp(session, keyword, data);   break;
  55.      case 'a':  res=QSetAccessOp(session, keyword);          break;
  56.      case 's':  res=QSetOp(session, keyword, data, dataLen); break;
  57.      case 'S':  res=QStreamOp(session, keyword, data, dataLen); break;
  58.      case 'r':  res=QRenameOp(session, keyword, data);       break;
  59.      case 'D':  res=QDebugOp(session, keyword);              break;
  60.      case 'g':  res=QGetOp(session, keyword, -1);            break;
  61.      case 'd':  res=QDeleteOp(session, keyword);             break;
  62.      case 'i':  res=QInfoOp(session);                        break;
  63.      case 'c':  res=QSubscribeOp(session, keyword, -1);      break;
  64.      case 'C':  res=QGetAndSubscribeOp(session, keyword, -1);     break;
  65.      case 'k':  res=QClearSubscriptionsOp(session,atoi(keyword)); break;
  66.      case 'p':  res=QPingOp(session);                             break;
  67.      case 'v':  res=QRequestPrivilegesOp(session,atol(keyword));  break;
  68.      case 'w':  res=QReleasePrivilegesOp(session,atol(keyword));  break;
  69.      case '!':  res=QKillClientsOp(session,keyword);              break;
  70.      case '?':  res=QGetParameterOp(session,keyword);             break;
  71.      case '$':  res=QSetParameterOp(session,keyword,data);        break;
  72.      default:   printf("Command code %c was not recognized.\n",debugline[0]); break;
  73.    }
  74.    printf("(Op result was %i)\n",res);
  75.    if (debugline[0] == '\0') return;
  76.   }
  77. }
  78.  
  79.  
  80.  
  81. __geta4 void ChildThreadEntryFunc(void)
  82. {
  83.   if (QReattachSession(session, 0L) == FALSE) printf("Error: QReattachSession failed!  Press CTRL-C to exit.\n");
  84.   else
  85.   {
  86.     printf("Child thread is running!\n");
  87.     while(1)
  88.     {
  89.       struct QMessage * qMsg;
  90.       ULONG signals = (1L << session->qMsgPort->mp_SigBit) | (SIGBREAKF_CTRL_C) | (SIGBREAKF_CTRL_F);
  91.  
  92.       /* Wait for next message from the server */
  93.       signals = Wait(signals);
  94.       if (signals & (1L << session->qMsgPort->mp_SigBit))
  95.       {
  96.         while(qMsg = (struct QMessage *) GetMsg(session->qMsgPort))
  97.         {
  98.           struct QRunInfo * inf = (qMsg->qm_DataLen == sizeof(struct QRunInfo)) ? ((struct QRunInfo *) qMsg->qm_Data) : NULL;
  99.  
  100.           /* Handle message */
  101.           printf("Message %p recieved---------\n",qMsg);
  102.           printf("Status:       %i (%s)\n",  qMsg->qm_Status, QErrorName(qMsg->qm_Status));
  103.           printf("Error Line:   %i\n",  qMsg->qm_ErrorLine);
  104.           printf("Message ID:   %i\n",  qMsg->qm_ID);
  105.           printf("Path:        [%s]\n", qMsg->qm_Path?qMsg->qm_Path:"<NULL>");
  106.           printf("Data:        [%s](int=%i)\n", qMsg->qm_Data?qMsg->qm_Data:((UBYTE*)"<NULL>"),qMsg->qm_Data?(*((int*)qMsg->qm_Data)):0);
  107.           printf("DataLen:      %lu\n", qMsg->qm_DataLen);
  108.           printf("ActualLen:    %lu\n", qMsg->qm_ActualLen);
  109.  
  110.           if (inf) printf("Info: alloced:%li allowed:%li avail:%li curPrivs=0x%x posPrivs=0x%x\n",
  111.             inf->qr_Alloced, inf->qr_Allowed, inf->qr_Avail, inf->qr_CurrentPrivs, inf->qr_PossiblePrivs); 
  112.           FreeQMessage(session, qMsg);
  113.         }
  114.       }
  115.       if (signals & SIGBREAKF_CTRL_F) ProcessDebugCommands(session);
  116.       if (signals & SIGBREAKF_CTRL_C) break;  /* Quit if CTRL-C pressed */
  117.     }
  118.  
  119. #ifdef LET_CHILD_THREAD_FREE_THE_QSESSION
  120.     printf("Freeing QSession in child thread...\n");
  121.     QFreeSession(session);
  122.     session = NULL;  /* So that the main thread won't try to free it */
  123. #else  
  124.     if (QDetachSession(session, 0L) == FALSE) printf("Warning: Child's QDetachSession failed!\n");
  125.     /* Now the main thread is able to free the QSession. */
  126. #endif
  127.   }
  128.   
  129.   printf("Child thread is exiting...\n");
  130.   
  131.   /* Signals main thread to wake up... hacky method but it's just for this test proggy */
  132.   Forbid();  /* to make sure our thread has died before the code gets unloaded! */
  133.   waitForChildThread = FALSE;
  134. }
  135.  
  136. /* Main program */
  137. int main(int argc, char ** argv)
  138. {
  139.   char * connectTo, * progName;
  140.   int port;
  141.     
  142.   printf("Usage Note:  AMarqueeDebugMultiThread [hostname=localhost] [myname=debug] [port=2957]\n");  
  143.   signal(SIGINT, SIG_IGN);  /* Don't let DICE abort us abruptly */
  144.   
  145.   connectTo = (argc>1) ? argv[1] : "localhost";
  146.   progName  = (argc>2) ? argv[2] : "debug";
  147.   port      = (argc>3) ? atoi(argv[3]) : 2957;
  148.  
  149.   if ((AMarqueeBase = OpenLibrary("amarquee.library",47L)) == NULL)
  150.   {
  151.     printf("Couldn't open amarquee.library v47!\n");
  152.     exit(RETURN_ERROR);
  153.   }
  154.   printf("Connecting to %s:%i (allocating QSession in main thread)\n",connectTo, port);
  155.   if ((session = QNewSession(connectTo, port, progName)) == NULL)
  156.   {
  157.     printf("Couldn't connect to server %s:%i\n",connectTo, port);
  158.     exit(RETURN_WARN);
  159.   }
  160.   printf("Connected to server %s:%i\n",connectTo, port);
  161.  
  162.   /* Setup some sample data */
  163.   (void)QSetOp(session, "sampledata",             "Kids",    5);
  164.   (void)QSetOp(session, "sampledata/Jeremy",      "1",       2);
  165.   (void)QSetOp(session, "sampledata/Joanna",      "2",       2);
  166.   (void)QSetOp(session, "sampledata/Joanna/nerd", "yep! :)", 8);
  167.   (void)QSetOp(session, "sampledata/Joellen",     "3",       2);
  168.   (void)QSetOp(session, "sampledata/Charcoal",    "Kitty!",  7);
  169.   (void)QGetOp(session, "/#?/#?/#?/#?", -1);
  170.   (void)QGo(session, 0L);
  171.  
  172.   printf("Commands are:\n");
  173.   printf("\n");
  174.   printf("a wildhostpath   Access control (default is /#?/#?)\n");
  175.   printf("A wildhostpath   Access control for incoming messages (default in no access)\n");
  176.   printf("m hosts=data     Send an active message to hosts\n");
  177.   printf("M hosts=string   Send an system message to hosts\n");
  178.   printf("s path=data      Set data node value\n");
  179.   printf("S path=data      Stream data node value\n");
  180.   printf("r path=newlabel  Rename data node\n");
  181.   printf("D debugstring    Send debug string\n");
  182.   printf("g wildpath       Get a node or nodes\n");
  183.   printf("c wildpath       Subscribe to a node or nodes\n");
  184.   printf("C wildpath       Get&Subscribe to a node or nodes\n");
  185.   printf("k opID           Klear subscriptions (by id or 0 for all)\n");
  186.   printf("d wildpath       Delete a node or nodes\n");
  187.   printf("i                Request info packet\n");
  188.   printf("p                Request ping packet\n");
  189.   printf("v #              Request new privileges (by code bitchord)\n");
  190.   printf("w #              Release existing privileges (by code bitchord)\n");
  191.   printf("! hosts          Kill other clients (requires KILLCLIENTS privilege!)\n");
  192.   printf("$ param=string   Set a parameter with QSetParam()\n");
  193.   printf("? param          Get a parameter by name\n");
  194.   printf("<enter>          Send accumulated transactions (GO!!)\n");
  195.   printf("\n");
  196.   printf("Press CTRL-F to enter commands, or CTRL-C to quit\n");
  197.  
  198.   if (QDetachSession(session, 0L))  /* Make the QSession available to other threads */
  199.   {
  200.     struct Task * childThread;
  201.  
  202.     printf("Spawning child thread...\n");
  203.     if (childThread = CreateNewProcTags(NP_Entry, ChildThreadEntryFunc, NP_Name, "AMarqueeDebugMultiThread Child Process", TAG_END, NULL))
  204.     {
  205.       BOOL childGone = FALSE;
  206.       
  207.       while(1)
  208.       {
  209.         ULONG sigs = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F);
  210.         
  211.         if (sigs & SIGBREAKF_CTRL_C)
  212.         {
  213.           break;
  214.         }
  215.         if (sigs & SIGBREAKF_CTRL_F) Signal(childThread, SIGBREAKF_CTRL_F);
  216.       }
  217.         
  218.       printf("Main thread is waiting for child thread to die now.\n");
  219.       while(childGone == FALSE)
  220.       {
  221.         Delay(10);
  222.         Forbid();
  223.         if (waitForChildThread) Signal(childThread, SIGBREAKF_CTRL_C);
  224.                            else childGone = TRUE;
  225.         Permit();
  226.       }
  227.     } 
  228.   }
  229.   else printf("Error, couldn't Detach QSession from main thread\n");
  230.   
  231. printf("\nCleaning up...\n");
  232.   if (session)      
  233.   {
  234.     printf("Main thread is freeing the QSession.\n");
  235.     /* This MUST be done before we close the library.  
  236.        Furthermore, it must be done by the thread 
  237.        the Qsession is attached to (it can be done by any 
  238.        thread if the QSession is detached) */
  239.     QFreeSession(session);        
  240.   }
  241.   if (AMarqueeBase) CloseLibrary(AMarqueeBase);  
  242.   printf("All done.\n");
  243.  
  244.   return(0);
  245. }
  246.  
  247.